package com.isky.visual.proj.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.isky.visual.constant.CommonConstant;
import com.isky.visual.interceptor.PlatformUserManager;
import com.isky.visual.proj.config.PanelGroupTypeEnum;
import com.isky.visual.proj.config.ProjectStatusEnum;
import com.isky.visual.proj.entity.*;
import com.isky.visual.proj.entity.vo.ProjectMoveParam;
import com.isky.visual.proj.entity.vo.ProjectPageParam;
import com.isky.visual.proj.entity.vo.ProjectShareParam;
import com.isky.visual.proj.mapper.*;
import com.isky.visual.proj.service.IPanelGroupProjectService;
import com.isky.visual.proj.service.IProjectService;
import com.isky.visual.proj.service.IProjectShareUserGroupService;
import com.isky.visual.proj.service.IProjectShareUserService;
import com.isky.visual.system.config.SystemCodeEnum;
import com.isky.visual.system.entity.SystemConfiguration;
import com.isky.visual.system.service.ISystemConfigService;
import com.isky.visual.user.entity.User;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 发布可视化项目 服务实现类
 * </p>
 *
 * @author wudl
 * @since 2020-04-28
 */
@Service
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements IProjectService {

    @Autowired
    ProjectMapper projectMapper;

    @Autowired
    PanelGroupMapper panelGroupMapper;

    @Autowired
    IPanelGroupProjectService iPanelGroupProjectService;

    @Autowired
    IProjectShareUserGroupService iProjectShareUserGroupService;

    @Autowired
    IProjectShareUserService iProjectShareUserService;

    @Autowired
    ISystemConfigService iSystemConfigService;

    @Autowired
    TransactionTemplate transactionTemplate;

    @Override
    public boolean copy(Long groupId, Long projectId) {
        User user = PlatformUserManager.getUser();

        Project project = selectProjectById(projectId);
        if (project == null) {
            return false;
        }

        project.setId(null);
        project.setUserId(user.getId());

        Boolean execute = transactionTemplate.execute((status) -> {
            projectMapper.insert(project);

            PanelGroupProject panelGroupProject = new PanelGroupProject();
            panelGroupProject.setGroupId(groupId);
            panelGroupProject.setProjectId(project.getId());
            panelGroupProject.setValid(true);
            iPanelGroupProjectService.doInsert(panelGroupProject);
            return true;
        });

        return execute;
    }

    @Override
    public boolean delete(Long projectId) {
        Objects.requireNonNull(projectId);

        Project project = selectProjectById(projectId);
        if (project == null) {
            return false;
        }
        project.setValid(false);
        int update = projectMapper.updateById(project);
        return update > 0 ? true : false;
    }

    /**
     * TODO 仪表盘组类型分为 0 所有人公共  1 我的公共 2 我的 其中1 2 是在设计器上能看到的
     * 0是在设计器页面看不到的，他的作用 是挂载 分享给用户组的仪表盘。
     * 所以在查询 我的分组下的仪表盘可以直接用仪表盘组id去查询
     *
     * @param param
     * @return
     */
    @Override
    public List<Project> getProjectListPage(ProjectPageParam param) {
        if (param == null) {
            return null;
        }
        // 检验下当前panelGroup 的类型
//        PanelGroup panelGroup = panelGroupMapper.selectByGroupId(param.getGroupId());
//        if(panelGroup == null || !Objects.equals(panelGroup.getGroupType(),2) ){
//            return null;
//        }
        User user = PlatformUserManager.getUser();
        List<Project> projects = projectMapper.selectProjectPage(param.getStatus(), param.getGroupId(),PanelGroupTypeEnum.PERSON.getType(),user.getId());
        supplementaryInformation(projects);
        return projects;
    }

    /**
     * TODO 仪表盘组类型分为 0 所有人公共  1 我的公共 2 我的 其中1 2 是在设计器上能看到的
     * 0是在设计器页面看不到的，他的作用 是挂载 分享给用户组的仪表盘。
     * 所以在查询 我的分组下的仪表盘可以直接用仪表盘组id去查询
     * 在查询 公共分组下 非根目录下的仪表盘 可以直接用仪表盘组id去查询
     * 在查询 公共分组下 根目录下的仪表盘 需要去查询 分享给个人的仪表盘，分享给用户组的仪表盘
     * <p>
     * TODO 这个接口是专门用来查询公共的
     *
     * @param param
     * @return
     */
    @Override
    public List<Project> queryShareProjectList(ProjectPageParam param) {
        if (param == null) {
            return null;
        }

        User user = PlatformUserManager.getUser();
        List<Project> projects = null;
        if (param.getGroupId() != null) {
            // 检验下当前panelGroup 的类型
            PanelGroup panelGroup = panelGroupMapper.selectByGroupId(param.getGroupId());
            if (panelGroup == null || Objects.equals(panelGroup.getGroupType(), PanelGroupTypeEnum.PERSON.getType())) { // 我的
                return null;
            }

            if (Objects.equals(panelGroup.getGroupType(), PanelGroupTypeEnum.ALL_SHARE.getType())) {
                // 所有人共享的组： 查询别人直接分享给你，和分享给你所在的组
                projects = projectMapper.selectShareProjectPage(param.getStatus(), user.getId());
            } else if (Objects.equals(panelGroup.getGroupType(), PanelGroupTypeEnum.PERSON_SHARE.getType()) && Objects.equals(panelGroup.getParentId(), CommonConstant.PANEL_ROOT_ID)) {
                //公共 跟目录，查询别人直接分享给你，和分享给你所在的组 和上一个if一样，分开主要为后续个性化，直接在这里调整
                projects = projectMapper.selectShareProjectPage(param.getStatus(), user.getId());
            } else if (Objects.equals(panelGroup.getGroupType(), PanelGroupTypeEnum.PERSON_SHARE.getType())) {
                //公共 //不在跟目录，说明自己已经建立了仪表盘组，直接根据组id 查询
                projects = projectMapper.selectProjectPage(param.getStatus(), param.getGroupId(), PanelGroupTypeEnum.PERSON_SHARE.getType(), user.getId());
            }
        } else {
            projects = new ArrayList<>();
            List<Project> projects1 = projectMapper.selectShareProjectPage(param.getStatus(), user.getId());
            projects.addAll(projects1);
            List<Project> projects2 = projectMapper.selectProjectPage(param.getStatus(), param.getGroupId(),PanelGroupTypeEnum.PERSON_SHARE.getType(),user.getId());
            projects.addAll(projects2);
        }
        projects = (List) projects.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Project::getId))), ArrayList::new));

        supplementaryInformation(projects);
        return projects;
    }

    @Override
    public boolean publish(Long projectId) {
        Objects.requireNonNull(projectId);

        Project project = new Project();
        project.setId(projectId);
        project.setUpdateTime(LocalDateTime.now());
        project.setStatus(ProjectStatusEnum.PUBLISH.getStatus());
        int update = projectMapper.updateByPrimary(project);
        return update > 0 ? true : false;
    }

    @Override
    public Project selectProjectById(Long projectId) {
        Project queryObject = new Project();
        queryObject.setValid(true);
        queryObject.setId(projectId);

        QueryWrapper<Project> queryWrapper = new QueryWrapper<>();
        queryWrapper.setEntity(queryObject);

        Project project = projectMapper.selectOne(queryWrapper);
        supplementaryInformation(project);
        return project;
    }

    private void supplementaryInformation(List<Project> projects) {
        if (projects != null && !projects.isEmpty()) {
            for (Project project : projects) {
                supplementaryInformation(project);
            }
        }
    }

    private void supplementaryInformation(Project project) {
        if (project != null) {
            String imageUrl = project.getImageUrl();
            if (StringUtils.isNotBlank(imageUrl) && !(imageUrl.startsWith("http") || imageUrl.startsWith("www."))) {
                //补充下图片信息
                SystemConfiguration systemConfiguration = iSystemConfigService.getByCode(SystemCodeEnum.PROJECT_IMAGE_URL.getCode());
                if (systemConfiguration != null) {
                    String url = String.format("%s/%s", systemConfiguration.getValue(), project.getImageUrl());
                    project.setImageUrl(url.replace("//", "/"));
                }
            }
        }
    }

    @Override
    public boolean insertProject(Long groupId, Project project) {
        User user = PlatformUserManager.getUser();
        if (user != null) {
            project.setUserId(user.getId());
            project.setCreateBy(user.getUsername());
        }
        if(groupId == null || Objects.equals(groupId,CommonConstant.PANEL_ROOT_ID)) {
            PanelGroup panelGroup = panelGroupMapper.selectRoot(PanelGroupTypeEnum.PERSON.getType(), user.getId());
            groupId= panelGroup.getGroupId();
        }
        project.setStatus(ProjectStatusEnum.NEW.getStatus());
        Long finalGroupId = groupId;
        Boolean execute = transactionTemplate.execute((status) -> {
            projectMapper.insert(project);

            PanelGroupProject panelGroupProject = new PanelGroupProject();
            panelGroupProject.setGroupId(finalGroupId);
            panelGroupProject.setProjectId(project.getId());
            panelGroupProject.setValid(true);
            iPanelGroupProjectService.doInsert(panelGroupProject);
            return true;
        });

        return execute;
    }

    @Override
    public boolean move(ProjectMoveParam moveParam) {
        Long[] projectIds = moveParam.getProjectIds();
        Long groupId = moveParam.getGroupId();
        if (projectIds == null || projectIds.length == 0 || groupId == null) {
            return false;
        }
        Boolean execute = transactionTemplate.execute((status) -> {
            List<PanelGroupProject> panelGroupProjects = iPanelGroupProjectService.selectByProjectId(new ArrayList<>(Arrays.asList(projectIds)));
            if (panelGroupProjects != null && !panelGroupProjects.isEmpty()) {
                for (PanelGroupProject panelGroupProject : panelGroupProjects) {
                    //查看当前项目组类型和所属 如果是大家共有的项目组，则copy到新组 ，否则更新
                    PanelGroup panelGroup = panelGroupMapper.selectByGroupId(panelGroupProject.getGroupId());
                    if (Objects.equals(panelGroup.getGroupType(), CommonConstant.PANEL_ROOT_ID)) {
                        PanelGroupProject p = new PanelGroupProject();
                        p.setGroupId(groupId);
                        p.setProjectId(panelGroupProject.getProjectId());
                        p.setValid(true);
                        iPanelGroupProjectService.doInsert(p);
                    } else {
                        panelGroupProject.setGroupId(groupId);
                        iPanelGroupProjectService.updateById(panelGroupProject);
                    }
                }
            }
            return true;
        });
        return execute;
    }

    @Override
    public boolean rename(Long id, String projectName) {
        if (id == null) {
            return false;
        }

        Project project = new Project();
        project.setId(id);
        project.setProjectName(projectName);
        projectMapper.updateByPrimary(project);
        return true;
    }

    @Override
    public boolean updateSelect(Project project) {
        if (project == null) {
            return false;
        }
        projectMapper.updateByPrimary(project);
        return true;
    }

    @Override
    public boolean share(ProjectShareParam projectShareParam) {
        Long projectId = projectShareParam.getProjectId();
        Long[] groups = projectShareParam.getGroups();
        Long[] users = projectShareParam.getUsers();

        if (projectId == null) {
            return false;
        }

        Boolean execute = transactionTemplate.execute((status) -> {
            //查询所有人共有项目组的信息
            PanelGroup groupShareRoot= panelGroupMapper.selectAllShareRoot();
            if(groupShareRoot == null){
                groupShareRoot = new PanelGroup();
                groupShareRoot.setValid(true);
                groupShareRoot.setParentId(CommonConstant.PANEL_ROOT_ID);
                groupShareRoot.setGroupType(PanelGroupTypeEnum.ALL_SHARE.getType());
                panelGroupMapper.insert(groupShareRoot);
                groupShareRoot.setGroupId(groupShareRoot.getId());
                panelGroupMapper.updateById(groupShareRoot);
            }
            //分享给用户组
            if (groups != null && groups.length > 0) {
                for (Long id : groups) {
                    PanelGroupProject panelGroupProject = new PanelGroupProject();
                    panelGroupProject.setValid(true);
                    panelGroupProject.setGroupId(groupShareRoot.getGroupId());
                    panelGroupProject.setProjectId(projectId);
                    iPanelGroupProjectService.doInsert(panelGroupProject);

                    ProjectShareUserGroup projectShareUserGroup = new ProjectShareUserGroup();
                    projectShareUserGroup.setValid(true);
                    projectShareUserGroup.setProjectId(projectId);
                    projectShareUserGroup.setUserGroupId(id);
                    iProjectShareUserGroupService.doInsert(projectShareUserGroup);
                }
            }

            //分享给用户
            if (users != null && users.length > 0) {
                for (Long id : users) {
                    PanelGroupProject panelGroupProject = new PanelGroupProject();
                    panelGroupProject.setValid(true);
                    panelGroupProject.setGroupId(groupShareRoot.getGroupId());
                    panelGroupProject.setProjectId(projectId);
                    iPanelGroupProjectService.doInsert(panelGroupProject);

                    ProjectShareUser projectShareUser = new ProjectShareUser();
                    projectShareUser.setValid(true);
                    projectShareUser.setUserId(id);
                    projectShareUser.setProjectId(projectId);
                    iProjectShareUserService.doInsert(projectShareUser);
                }
            }
            return true;
        });
        return execute;
    }

    @Override
    public List<String> queryByUserGroupId(Long id) {
        return projectMapper.queryProjectNameByUserGroupId(id);
    }

    @Override
    public List<String> queryByUserId(Long id) {
        List<String> result = new ArrayList<String>(0);

        List<Project> projects = new ArrayList<>();
        List<Project> projects1 = projectMapper.selectShareProjectPage(null, id);
        projects.addAll(projects1);
        List<Project> projects2 = projectMapper.selectProjectPage(null, null, null, id);
        projects.addAll(projects2);

        projects = (List) projects.stream().collect(Collectors.collectingAndThen(
                Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Project::getId))), ArrayList::new));

        if (!projects.isEmpty()) {
            for (Project project : projects) {
                result.add(project.getProjectName());
            }
        }
        return result;
    }

}
